package com.dz.lm.common.utils;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.cxf.common.util.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;

public class XmlResolve {
	
	protected static Logger logger = LoggerFactory.getLogger(XmlResolve.class);
	
	/**
	 * map转化为xml消息体
	 * 
	 * @param map
	 * @return String
	 * @throws DocumentException
	 */
	public static String callMapToXML(Map<String, Object> map) {
		System.out.println("将Map转成Xml, Map：" + map.toString());
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		mapToXMLTest2(map, sb);
		sb.append("</xml>");
		System.out.println("将Map转成Xml, Xml：" + sb.toString());
		try {
			return sb.toString();
		} catch (Exception e) {
			System.out.println(e.toString());
		}
		return null;
	}

	private static void mapToXMLTest2(Map<String, Object> map, StringBuffer sb) {
		Set<String> set = map.keySet();
		for (Iterator<String> it = set.iterator(); it.hasNext();) {
			String key = (String) it.next();
			Object value = map.get(key);
			if (null == value)
				value = "";
			if (value.getClass().getName().equals("java.util.ArrayList")) {
				ArrayList keyList = (ArrayList<?>) map.get(key);
				sb.append("<" + key + ">");
				for (int i = 0; i < keyList.size(); i++) {
					HashMap hm = (HashMap) keyList.get(i);
					mapToXMLTest2(hm, sb);
				}
				sb.append("</" + key + ">");
			} else {
				if (value instanceof HashMap) {
					sb.append("<" + key + ">");
					mapToXMLTest2((HashMap) value, sb);
					sb.append("</" + key + ">");
				} else {
					sb.append("<" + key + ">" + value + "</" + key + ">");
				}
			}
		}
	}
	
	/**
	 * 根据xml消息体转化为Map
	 * 
	 * @param xml
	 * @param rootElement
	 * @return
	 * @throws DocumentException
	 */
	public static Map<String, Object> callXMLToMap(String xmlStr) {
		try {
			System.out.println(xmlStr);
			StringReader sr = new StringReader(xmlStr.toString());
			InputSource is = new InputSource(sr);
			SAXBuilder sax = new SAXBuilder();
			Document doc = sax.build(is);
			String filterstr = "";
			Map<String, Object> retrunData = getResultMap(doc, filterstr);
			return retrunData;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Map<String, Object> getResultMap(Document doc, String filterStr) {
		if (doc == null)
			return null;
		Element root = (Element) doc.getRootElement();
		Map<String, Object> map = new HashMap<String, Object>();;
		for (Iterator<Element> iterator = root.getChildren().iterator(); iterator.hasNext();) {
			Element e = iterator.next();
			List<Element> list = e.getChildren();
			if (list.size() > 0) {
				map.put(e.getName().toLowerCase(), getChildMap(e, filterStr));
			} else
				map.put(e.getName().toLowerCase(), e.getText());
		}
		return map;
	}

	public static Map getChildMap(Element e, String filterStr) {
		Map map = new HashMap();
		List childrenList = e.getChildren();
		if (childrenList.size() > 0) {
			for (int i = 0; i < childrenList.size(); i++) {
				Element iter = (Element) childrenList.get(i);
				List mapList = new ArrayList();

				if (iter.getChildren().size() > 0) {
					if (validateName(iter, filterStr)) {// 过滤在filterStr中包含的值
						Map m = getChildMap(iter, filterStr);
						if (map.get(iter.getName()) != null) {
							Object obj = map.get(iter.getName());
							if (!obj.getClass().getName().equals("java.util.ArrayList")) {
								mapList = new ArrayList();
								mapList.add(obj);
								mapList.add(m);
							}
							if (obj.getClass().getName().equals("java.util.ArrayList")) {
								mapList = (List) obj;
								mapList.add(m);
							}
							map.put(iter.getName().toLowerCase(), mapList);
						} else
							map.put(iter.getName().toLowerCase(), m);
					}

				} else {
					if (validateName(iter, filterStr)) {// 过滤在filterStr中包含的值
						if (map.get(iter.getName()) != null) {
							Object obj = map.get(iter.getName());
							if (!obj.getClass().getName().equals("java.util.ArrayList")) {
								mapList = new ArrayList();
								mapList.add(obj);
								mapList.add(iter.getText());
							}
							if (obj.getClass().getName().equals("java.util.ArrayList")) {
								mapList = (List) obj;
								mapList.add(iter.getText());
							}
							map.put(iter.getName().toLowerCase(), mapList);
						} else
							map.put(iter.getName().toLowerCase(), iter.getText());
					}

				}
			}
		} else
			map.put(e.getName(), e.getText());
		return map;
	}

	/** 判断含有子节点的name子节点的值或单个节点的值是否在filterContent中存在 */
	public static boolean validateName(Element iter, String filterContent) {
		List children = iter.getChildren();
		if (children.size() > 0) {
			for (int i = 0; i < children.size(); i++) {
				Element child = (Element) children.get(i);
				if ("name".equals(child.getName())
						&& filterContent.contains(child.getText())) {
					return false;
				}
			}
		} else {
			if (filterContent.contains(iter.getText())) {
				return false;
			}
		}
		return true;
	}
	
	//XML转字符串   原样取出
	public static String getXmlString(Document doc) {
		TransformerFactory tf = TransformerFactory.newInstance();
		try {
			Transformer t = tf.newTransformer();
			t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");// 解决中文问题，试过用GBK不行
			t.setOutputProperty(OutputKeys.METHOD, "html");
			t.setOutputProperty(OutputKeys.VERSION, "4.0");
			t.setOutputProperty(OutputKeys.INDENT, "no");
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			t.transform(new DOMSource(), new StreamResult(bos));
			return bos.toString();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
		return "";
	}
	
	/**
	 * 获取xml中某一节点内容
	 * 
	 * @param Document
	 * @param tagName
	 * @return 
	 */
	public static String getValueByTagName(Document doc, String tagName) {
		if (doc == null || StringUtils.isEmpty(tagName)) {
			return "";
		}
		Object obj = doc.getProperty(tagName);
		if (obj != null && obj.toString().length() > 0) {
			return obj.toString();
		}
		return "";
	}

	/**
	 * 响应xml
	 * 
	 * @param response
	 * @param content
	 * @return 
	 */
	public static String responseContent(String url,String xmlFileName, String xmlString) { //创建httpclient工具对象   
	    HttpClient client = new HttpClient();    
	    //创建post请求方法   
	    PostMethod myPost = new PostMethod(url);    
	    //设置请求超时时间   
	    client.setConnectionTimeout(3*1000);  
	    String responseString = null;    
	    try{    
	        //设置请求头部类型   
	        myPost.setRequestHeader("Content-Type","text/xml");  
	        myPost.setRequestHeader("charset","utf-8");  
	          
	        //设置请求体，即xml文本内容，注：这里写了两种方式，一种是直接获取xml内容字符串，一种是读取xml文件以流的形式   
	        myPost.setRequestBody(xmlString);   
	          
	        InputStream body = null;//XmlResolve.getClass().getResourceAsStream("/"+xmlFileName);  
	        myPost.setRequestBody(body);  
	          myPost.setRequestEntity(new StringRequestEntity(xmlString,"text/xml","utf-8"));     
	        int statusCode = client.executeMethod(myPost);    
	        if(statusCode == HttpStatus.SC_OK){    
	            BufferedInputStream bis = new BufferedInputStream(myPost.getResponseBodyAsStream());    
	            byte[] bytes = new byte[1024];    
	            ByteArrayOutputStream bos = new ByteArrayOutputStream();    
	            int count = 0;    
	            while((count = bis.read(bytes))!= -1){    
	                bos.write(bytes, 0, count);    
	            }    
	            byte[] strByte = bos.toByteArray();    
	            responseString = new String(strByte,0,strByte.length,"utf-8");    
	            bos.close();    
	            bis.close();    
	        }    
	    }catch (Exception e) {    
	        e.printStackTrace();    
	     }    
	     myPost.releaseConnection();    
	     return responseString;  
	}
	
	public static void main(String[] args) {
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("tx_cde", "YC00005");
		map.put("tx_type", "01");
		map.put("input_src", "06");
		String strXml = callMapToXML(map);

		map = new HashMap<String,Object>();
		map = callXMLToMap(strXml);
		System.out.println(map.toString());
	}
}
